﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Windows.Forms;

namespace WordCount
{
    class WC
    {
        public string fileName;    //文件名
        string[] FileName;    //指定目录下的文件集合
        string OutfileName;    //输出文件名
        string StopList;    //停用词表
        int LinesNumber = 0;    //行数
        int WordNumber = 0;    //单词数
        int CharNumber = 0;    //字符数
        int NullNumber = 0;    //空行数
        int NotesNumber = 0;    //注释行数 
        bool iso = false;    //是否保存
        List<string> content = new List<string>();    //将保存的信息

        //命令检测
        public string[] Check(string[] str)
        {
            if (str.Length == 0)    //未输入命令时输入命令
            {
                str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            }
            if (str.Length == 1)
            {
                if (str[0] != "-x")    //未正确输入“-x”命令
                {
                    Console.WriteLine("格式输入错误，请重新输入");
                    str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    return Check(str);
                }
                else return str;
            }
            else
            {
                int i = 0;    //所检测到的命令位置
                foreach (string s in str)
                {
                    i++;
                    if (s.Contains(".c") || str.Contains(".cs"))    //获取待统计文件
                    {
                        fileName = s;
                    }
                    else if (s == "-x")    //未正确输入“-x”命令
                    {
                        Console.WriteLine("“-x”命令应独立使用，请重新输入");
                        str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        return Check(str);
                    }
                    else if (s != "-c" && s != "-w" && s != "-l" && s != "-a" && s != "-s" && s != "-e" && s != "-o" && !s.Contains(".txt"))    //检测是否为正确命令
                    {
                        Console.WriteLine("{0}为非法命令,请重新输入", s);
                        str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                        return Check(str);
                    }
                    else if (s == "-o")    //检测“-o”命令格式是否输入正确
                    {
                        try
                        {
                            if (str[i].Contains(".txt"))    //“-o”命令格式输入正确
                                OutfileName = str[i];    //获取输出文件
                            else                             //“-o”命令格式输入不正确
                            {
                                Console.WriteLine("“-o”命令后应该接输出文件名，请重新输入");
                                str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                return Check(str);
                            }
                        }
                        catch              //“-o”命令格式输入不正确
                        {
                            Console.WriteLine("“-o”命令后应该接输出文件名，请重新输入");
                            str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            return Check(str);
                        }
                    }
                    else if (s == "-e")       //检测“-e”命令格式是否输入正确
                    {
                        try
                        {
                            if (str[i].Contains(".txt"))    //“-e”命令格式输入正确
                                StopList = str[i];    //获取停用词表
                            else                           //“-e”命令格式输入不正确
                            {
                                Console.WriteLine("“-e”命令后应该接停用词表文件名，请重新输入");
                                str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                return Check(str);
                            }
                        }
                        catch                     //“-e”命令格式输入不正确
                        {
                            Console.WriteLine("“-e”命令后应该接停用词表文件名，请重新输入");
                            str = Console.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            return Check(str);
                        }
                    }
                }
                if (fileName == null)    //检测是否输入待统计文件
                {
                    Console.WriteLine("请输入待统计文件");
                    fileName = Console.ReadLine();
                    while (!fileName.Contains(".c") && !fileName.Contains(".cs"))    //检测文件格式是否正确
                    {
                        Console.WriteLine("待统计文件应该为.c文件或.cs文件，请重新输入文件");
                        fileName = Console.ReadLine();
                    }
                }
                return str;
            }
        }

        //统计.c文件信息
        public void CountData(string filename)
        {
            int linesNumber = 0;    //行数
            int wordNumber = 0;    //单词数
            int charNumber = 0;    //字符数
            int nullNumber = 0;    //空行数
            int notesNumber = 0;    //注释行数 
            List<string> word = new List<string>();    //停用词组
            if (fileName != null)
            {
                if (File.Exists(fileName))
                {
                    FileStream fs = new FileStream(fileName, FileMode.Open);    //打开待统计文件
                    StreamReader sr = new StreamReader(fs);
                    if (StopList != null && File.Exists(StopList))    //当使用了停用词表
                    {
                        FileStream f = new FileStream(StopList, FileMode.Open);    //打开停用词表文件
                        StreamReader s = new StreamReader(fs);
                        string buf;
                        while ((buf = s.ReadLine()) != null)
                        {
                            string[] Str = buf.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                            for (int i = 0; i < Str.Length; i++)
                            {
                                word.Add(Str[i]);    //将停用词读入停用词组
                            }
                        }
                    }
                    string line;
                    //定义一个字符数组
                    char[] symbol = { ' ', '\t', ',', '.', '?', '!', ':', ';', '\'', '\"', '\n', '{', '}', '(', ')', '+', '-', '*', '=' };
                    while ((line = sr.ReadLine()) != null)
                    {
                        linesNumber++;     //统计行数
                        string[] str = line.Split(symbol, StringSplitOptions.RemoveEmptyEntries);
                        wordNumber += str.Length;    //统计单词数
                        for (int i = 0; i < str.Length; i++)
                        {
                            foreach (string s in word)
                            {
                                if (str[i] == s)
                                {
                                    wordNumber--;    //除去停用词表的单词数
                                    break;
                                }
                            }
                        }
                        if (line.Length == 0)
                        {
                            nullNumber++;    //统计空行数
                        }
                        else
                        {
                            if (line.Contains("//"))    //统计注释行数
                            {
                                notesNumber++;
                            }
                            charNumber += line.Replace(" ", "").Length;    //统计字符数
                        }
                    }
                    sr.Close();
                    LinesNumber = linesNumber;
                    WordNumber = wordNumber;
                    CharNumber = charNumber;
                    NullNumber = nullNumber;
                    NotesNumber = notesNumber;
                }
                else
                {
                    Console.WriteLine("待统计文件不存在,请重新输入文件地址");
                    fileName = Console.ReadLine();
                    CountData(fileName);
                }
            }
        }

        //执行命令
        public void ExecutiveCommand(string[] str, int n)
        {
            bool isc = false;    //是否执行“-c”命令
            bool isw = false;    //是否执行“-w”命令
            bool isl = false;    //是否执行“-l”命令
            bool isa = false;    //是否执行“-a”命令
            bool iss = false;    //是否执行“-s”命令
            foreach (string s in str)
            {
                switch (s)    //判断是否执行某命令
                {
                    case "-c":
                        isc = true;
                        break;
                    case "-w":
                        isw = true;
                        break;
                    case "-l":
                        isl = true;
                        break;
                    case "-a":
                        isa = true;
                        break;
                    case "-o":
                        iso = true;
                        break;
                    case "-s":
                        iss = true;
                        List<string> list = new List<string>();
                        string[] strC = Directory.GetFiles(fileName.Remove(fileName.LastIndexOf("\\")), "*.c", SearchOption.AllDirectories);    //获取目录下.c或.cs文件集合
                        string[] strCS = Directory.GetFiles(fileName.Remove(fileName.LastIndexOf("\\")), "*.cs", SearchOption.AllDirectories);
                        foreach(string C in strC)
                        {
                            list.Add(C);
                        }
                        foreach (string CS in strC)
                        {
                            list.Add(CS);
                        }
                        FileName = list.ToArray();    //将检索到的文件导入FileName中
                        break;
                    case "-x":
                        OpenFileDialog openFile = new OpenFileDialog();
                        if (openFile.ShowDialog() == DialogResult.OK)    //打开可是界面选择文件
                            fileName = openFile.FileName;
                        CountData(fileName);    //统计选定的文件信息
                                                //返回所以统计信息
                        isc = true;
                        isw = true;
                        isl = true;
                        isa = true;
                        iso = true;
                        break;
                    default:
                        break;
                }
            }
            //按固定格式输出统计信息
            if (isc)
                Console.WriteLine(fileName + ",字符数：" + CharNumber);
            if (isw)
                Console.WriteLine(fileName + ",单词数：" + WordNumber);
            if (isl)
                Console.WriteLine(fileName + ",行数：" + LinesNumber);
            if (isa)
                Console.WriteLine(fileName + ",代码行/空行/注释行：" + "{0}/{1}/{2}", LinesNumber, NullNumber, NotesNumber);
            //递归处理目录下所有文件
            if (iss)
            {
                if (n < FileName.Length)
                {
                    Console.WriteLine();
                    fileName = FileName[n];
                    CountData(fileName);
                    ExecutiveCommand(str, n);
                    n++;
                }
            }
            // 按指定格式保存信息
            if (iso)
            {
                if (isc)
                    content.Add(fileName + ",字符数：" + CharNumber.ToString());
                if (isw)
                    content.Add(fileName + ",单词数：" + WordNumber.ToString());
                if (isl)
                    content.Add(fileName + ",行数：" + LinesNumber.ToString());
                if (isa)
                    content.Add(fileName + ",代码行/空行/注释行：" + LinesNumber.ToString() + "/" + NullNumber.ToString() + "/" + NotesNumber.ToString());
            }
        }

        //保存统计信息
        public void Save()
        {
            if (iso)
            {
                if (OutfileName == null)
                    OutfileName = "result.txt";
                FileStream aFile = new FileStream(OutfileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                StreamWriter sw = new StreamWriter(aFile);
                foreach (string str in content)
                {
                    sw.WriteLine(str);
                }
                sw.Close();                                     //释放文件
                aFile.Close();
                sw.Dispose();                                   //释放资源
                aFile.Dispose();
                Console.WriteLine("保存成功");
            }
        }
    }
}
